/*
    Dijjer - A Peer to Peer HTTP Cache
    Copyright (C) 2008 Mathias De Maré

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package dijjer;

import java.io.DataInputStream;
import java.util.StringTokenizer;

import dijjer.io.comm.AbstractMulticastSocketManager;
import dijjer.io.comm.AbstractPeer;
import dijjer.io.comm.AbstractRoutingTable;
import dijjer.io.comm.AbstractUdpSocketManager;
import dijjer.updater.AbstractResourceManager;
import dijjer.updater.Loader;
import dijjer.util.logging.Logger;

public abstract class AbstractFactory {
	public static final String WEBFACTORY = "www";
	
	private static boolean set = false;
	private static AbstractFactory factory;
	
	protected static boolean resourceManagerSet = false;
	protected static AbstractResourceManager rm;
	
	public static void configure(String[] args) {
		for(int i=0; i<args.length; i++) {
			String pluginName = "--plugin=";
			if(args[i].startsWith(pluginName)) {
				setFactory(args[i].substring(pluginName.length()));
				return;
			}
		}
		// default to web-factory
		if(!set)
		    setFactory(WEBFACTORY);
	}

	private static void setFactory(String factoryType) {
		if(set) {
			Logger.warning("Factory already set!");
			return;
		}
		if(factoryType.equals(WEBFACTORY)) {
			factory = new WebFactory();
		} else {
			try {
				factory = Loader.loadPlugin(factoryType);
			} catch (Exception e) {
				Logger.fatal(1, "Failed to load communication plugin.", e);
			}
		}
		set = true;
	}
	
	public static AbstractFactory getFactory() {
		if(set)
			return factory;
		else
			return null;
	}
	
	public AbstractPeer[] getPeers(String destString, String separators) {
		StringTokenizer st = new StringTokenizer(destString,separators);
		AbstractPeer[] peers = new AbstractPeer[st.countTokens()];
		while(st.hasMoreTokens()) {
			int position = st.countTokens()-1;
			try {
				peers[position] = getFactory().getPeer((String) st.nextElement());
			}
			catch(Exception e) {
				Logger.warning("AbstractFactory: failed Peer creation.");
				peers[position] = null;
			}
		}
		return peers;
	}
	
	public abstract AbstractPeer getPeer(String destString) throws Exception;
	
	public abstract AbstractPeer getPeer() throws Exception;
	
	public abstract AbstractPeer getPeer(DataInputStream dis) throws Exception;
	
	public abstract AbstractUdpSocketManager getUdpSocketManager() ;
	
	public abstract void initUdpSocketManager(int externalListenPort) throws Exception;
	
	public abstract AbstractMulticastSocketManager getMulticastSocketManager();
	
	public abstract void initMulticastSocketManager(int externalListenPort) throws Exception;
	
	public abstract AbstractResourceManager getResourceManager();
	
	public abstract boolean isSiteLocal(String addr);
	
	public abstract AbstractPeer getMulticastPeer() throws Exception;
	
	public abstract void initRoutingTable(int routingTableSize) throws Exception;
	
	public abstract AbstractRoutingTable getRoutingTable();
	
}
